/*****************************************************************************************
   
   Copyright (c) Microsoft Corporation. All rights reserved.

   Use of this code sample is subject to the terms of the Microsoft
   Permissive License, a copy of which should always be distributed with
   this file.  You can also access a copy of this license agreement at:
   http://www.microsoft.com/resources/sharedsource/licensingbasics/permissivelicense.mspx

 ****************************************************************************************/

using System;

namespace GrooveWebServicesV12Helpers
{
	/// <summary>
	/// Subscription for web services events.
	/// Applications will usually not use this class directly; instead use the event delegates in each data class.
	/// </summary>
	public class Subscription
	{
		private GrooveWebServicesV12Helpers.Context m_Context;

		private GrooveSubscriptionsWebService.GrooveSubscriptions m_GrooveSubscriptions;

		internal const int DEFAULT_TIME_TO_LIVE_IN_HOURS = 8;

		private string m_IdentityURL;
		private string m_EventClass;
		private string m_SourceURI;
		private string m_CallbackURI;
		private string m_SubscriptionID;
        private string m_ErrorMsg;

		private int m_TimeToLive;

		//  Aggregated subscription member variables
		private string m_Query;
		private string[] m_SourceURIs;

		public Subscription(GrooveWebServicesV12Helpers.Context i_Context, string i_IdentityURL, string i_EventClass, string i_SourceURI, string i_CallbackURI)
			: this(i_Context, i_IdentityURL, i_EventClass, null, i_SourceURI, i_CallbackURI, null, DEFAULT_TIME_TO_LIVE_IN_HOURS, true)
		{
		}

		public Subscription(GrooveWebServicesV12Helpers.Context i_Context, string i_IdentityURL, string i_EventClass, string i_SourceURI, string i_CallbackURI, string i_SubscriptionID)
			: this(i_Context, i_IdentityURL, i_EventClass, null, i_SourceURI, i_CallbackURI, i_SubscriptionID, DEFAULT_TIME_TO_LIVE_IN_HOURS, true)
		{
		}

		public Subscription(GrooveWebServicesV12Helpers.Context i_Context, string i_IdentityURL, string i_EventClass, string i_SourceURI, string i_CallbackURI, string i_SubscriptionID, int i_TimeToLive)
			: this(i_Context, i_IdentityURL, i_EventClass, null, i_SourceURI, i_CallbackURI, i_SubscriptionID, i_TimeToLive, true)
		{
		}

		public Subscription(GrooveWebServicesV12Helpers.Context i_Context, string i_IdentityURL, string i_EventClass, string i_Query, string i_SourceURI, string i_CallbackURI, string i_SubscriptionID, int i_TimeToLive)
			: this(i_Context, i_IdentityURL, i_EventClass, i_Query, i_SourceURI, i_CallbackURI, i_SubscriptionID, i_TimeToLive, true)
		{
		}

		public Subscription(GrooveWebServicesV12Helpers.Context i_Context, string i_IdentityURL, string i_EventClass, string i_Query, string i_SourceURI, string i_CallbackURI, string i_SubscriptionID, int i_TimeToLive, bool i_StartSubscription)
		{
			m_Context = i_Context;

			m_IdentityURL = i_IdentityURL;
			m_EventClass = i_EventClass;
			m_Query = i_Query;
			m_CallbackURI = i_CallbackURI;
			m_SubscriptionID = i_SubscriptionID;
			m_TimeToLive = i_TimeToLive;

            if (i_SourceURI.IndexOf(":") >= 0)
                throw new System.ArgumentException("SourceURI can not contain a ':' character!");

            m_SourceURI = i_SourceURI;

            m_ErrorMsg = null;

			if (i_StartSubscription)
				this.Start();
		}

        public Subscription(Subscription i_Subscription, Context i_NewContext)
        {
            m_Context = i_NewContext;

            m_IdentityURL = i_Subscription.m_IdentityURL;
            m_EventClass = i_Subscription.m_EventClass;
            m_Query = i_Subscription.m_Query;
            m_CallbackURI = i_Subscription.m_CallbackURI;
            m_SubscriptionID = i_Subscription.m_SubscriptionID;
            m_TimeToLive = i_Subscription.m_TimeToLive;
            m_SourceURI = i_Subscription.m_SourceURI;
        }

		#region Subscription Properties And Methods

		public static GrooveSubscriptionsWebService.GrooveSubscriptions CreateInitializedSubscriptionsWebService(string i_IdentityURL, string i_TargetURI, GrooveWebServicesV12Helpers.Context i_Context)
		{
			//  Create the service
			GrooveSubscriptionsWebService.GrooveSubscriptions SubscriptionsWebService = new GrooveSubscriptionsWebService.GrooveSubscriptions();

			//  Create the Groove SOAP header
			SubscriptionsWebService.GrooveRequestHeaderValue = new GrooveSubscriptionsWebService.GrooveRequestHeader();

			//  Set appropriate header values
			SubscriptionsWebService.GrooveRequestHeaderValue.GrooveRequestKey = i_Context.RequestKey;
			SubscriptionsWebService.GrooveRequestHeaderValue.GrooveIdentityURL = i_IdentityURL;

			//  Set the URL
			SubscriptionsWebService.Url = i_Context.Host + i_TargetURI;

			//  Set Timeout
			SubscriptionsWebService.Timeout = i_Context.Timeout;

			return SubscriptionsWebService;
		}

		public GrooveWebServicesV12Helpers.Context Context
		{
			get
			{
				return m_Context;
			}
		}

		public string IdentityURL
		{
			get
			{
				return m_IdentityURL;
			}
		}

		public string EventClass
		{
			get
			{
				return m_EventClass;
			}
		}

		public string Query
		{
			get
			{
				return m_Query;
			}
		}

		public string SourceURI
		{
			get
			{
				return m_SourceURI;
			}
		}

		public string CallbackURI
		{
			get
			{
				return m_CallbackURI;
			}
		}

		public string SubscriptionID
		{
			get
			{
				return m_SubscriptionID;
			}
		}

        public int TimeToLive
        {
            get
            {
                return m_TimeToLive;
            }
        }

        public string ErrorMsg
        {
            get
            {
                return m_ErrorMsg;
            }

            internal set
            {
                m_ErrorMsg = value;
            }
        }

		public string[] SourceURIs
		{
			get
			{
				if (System.String.IsNullOrEmpty(m_Query))
					throw new System.Exception("This property is only valid for aggregated subscriptions");

				return m_SourceURIs;
			}
		}

		public string Start()
		{
			//  If subscription ID already exists, update subscription and exit
			if (!System.String.IsNullOrEmpty(m_SubscriptionID))
			{
				this.Update();
			}
			else
			{
				//  Get initialized reference to web service
				GrooveSubscriptionsWebService.GrooveSubscriptions SubscriptionsWebService = this.GetInitializedSubscriptionsWebService(GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SUBSCRIPTIONS_URI);

				System.DateTime BeginDateTime = System.DateTime.Now;

                //  -------------------------------------------------------------------------
                //  BIG HONKING NOTE:  We do explicitly do a null check here because "" means
                //                     that we should use an aggregated subscription

                    bool IsAggregatedSubscription = (m_Query != null);

                //  -------------------------------------------------------------------------

				if (!IsAggregatedSubscription)
				{
					//  Create subscription
					m_SubscriptionID = SubscriptionsWebService.Create
						(
						m_EventClass,
						m_SourceURI,
						m_CallbackURI,
						m_TimeToLive
						);

					if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
					{
						System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
						System.Diagnostics.Debug.WriteLine("SubscriptionsWebService::Create, " + TimeSpan.TotalMilliseconds + " ms");
					}
				}
				else if (Context.Groove12)
				{
					//  Create aggregated subscription
					GrooveSubscriptionsWebService.AggregateData AggregateData = SubscriptionsWebService.CreateAggregated2
						(
						m_EventClass,
						m_Query,
						m_SourceURI,
						m_CallbackURI,
						m_TimeToLive
						);

					if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
					{
						System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
						System.Diagnostics.Debug.WriteLine("SubscriptionsWebService::CreateAggregated2, " + TimeSpan.TotalMilliseconds + " ms");
					}

					m_SubscriptionID = AggregateData.SubscriptionID;
					m_SourceURIs = AggregateData.SourceURIs;
				}
                else 
                {
                    //  Create aggregated subscription
                    GrooveSubscriptionsWebService.AggregateData AggregateData = SubscriptionsWebService.CreateAggregated
                        (
                        m_EventClass,
                        m_Query,
                        m_SourceURI,
                        m_CallbackURI,
                        m_TimeToLive
                        );

                    if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
                    {
                        System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
                        System.Diagnostics.Debug.WriteLine("SubscriptionsWebService::CreateAggregated2, " + TimeSpan.TotalMilliseconds + " ms");
                    }

                    m_SubscriptionID = AggregateData.SubscriptionID;
                    m_SourceURIs = AggregateData.SourceURIs;
                }
            }

			return m_SubscriptionID;
		}

		public void Update()
		{
			if (System.String.IsNullOrEmpty(m_SubscriptionID))
				throw new System.Exception("Subscription not started!");

			//  Get initialized reference to web service
			GrooveSubscriptionsWebService.GrooveSubscriptions SubscriptionsWebService = this.GetInitializedSubscriptionsWebService(GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SUBSCRIPTIONS_URI);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Ask service to update subscription
			SubscriptionsWebService.Update
				(
				m_SubscriptionID, 
				m_TimeToLive
				);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SubscriptionsWebService::Update, " + TimeSpan.TotalMilliseconds + " ms");
			}
		}

		public void Stop()
		{
			if (System.String.IsNullOrEmpty(m_SubscriptionID))
				throw new System.Exception("Subscription not started!");

			//  Get initialized reference to web service
			GrooveSubscriptionsWebService.GrooveSubscriptions SubscriptionsWebService = this.GetInitializedSubscriptionsWebService(GrooveWebServicesV12Helpers.Shared.GROOVE_WEB_SERVICES_SUBSCRIPTIONS_URI);

			System.DateTime BeginDateTime = System.DateTime.Now;

			//  Destroy subscription
			SubscriptionsWebService.Delete(m_SubscriptionID);

			if (GrooveWebServicesV12Helpers.Context.TraceEnabled)
			{
				System.TimeSpan TimeSpan = System.DateTime.Now.Subtract(BeginDateTime);
				System.Diagnostics.Debug.WriteLine("SubscriptionsWebService::Delete, " + TimeSpan.TotalMilliseconds + " ms");
			}

			//  Indicate subscription deleted
			m_SubscriptionID = null;
		}

		private GrooveSubscriptionsWebService.GrooveSubscriptions GetInitializedSubscriptionsWebService(string i_TargetURI)
		{
            if ((m_GrooveSubscriptions == null) || Context.ReinitNeeded(m_GrooveSubscriptions.GrooveRequestHeaderValue.GrooveRequestKey))
			{
				m_GrooveSubscriptions = GrooveWebServicesV12Helpers.Subscription.CreateInitializedSubscriptionsWebService
					(
					m_IdentityURL,
					i_TargetURI,
					Context
					);
			}
			else
			{
				//  Explicitly overwrite target URL and Timeout
				m_GrooveSubscriptions.Url = Context.Host + i_TargetURI;
                m_GrooveSubscriptions.Timeout = Context.Timeout;
			}

			return m_GrooveSubscriptions;
		}

		#endregion

	}
}
